package br.com.ftt.database;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import br.com.ftt.exception.ConectionException;
import br.com.ftt.util.HibernateUtil;
import br.com.ftt.util.Util;

public class DaoGenericoImpl<T> implements IDaoGenerico<T>
{

	private final Class<T> oClass;

	@SuppressWarnings("unchecked")
	public DaoGenericoImpl()
	{
		this.oClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	@Override
	public Class<T> getObjectClass()
	{

		return oClass;
	}

	@SuppressWarnings("null")
	@Override
	public T save(T objeto) throws ConectionException
	{
		Session session = null;
		Transaction t = null;
		try
		{
			session = HibernateUtil.getSession().openSession();
			t = session.beginTransaction();
			session.saveOrUpdate(objeto);
			t.commit();

		}
		catch (HibernateException e)
		{
			Util.gravaLog(e.getMessage());
			t.rollback();
			throw new ConectionException(e.getMessage());

		}
		catch (ConectionException e)
		{
			Util.gravaLog(e.getMessage());
			t.rollback();
			throw e;
		}
		finally
		{
			if (session.isOpen())
				session.close();

		}
		return (T) objeto;
	}

	@SuppressWarnings("null")
	@Override
	public void delete(T objeto) throws ConectionException
	{
		Session session = null;
		Transaction t = null;
		try
		{
			session = HibernateUtil.getSession().openSession();
			t = session.beginTransaction();
			session.delete(objeto);
			t.commit();
		}
		catch (HibernateException e)
		{
			Util.gravaLog(e.getMessage());
			t = session.beginTransaction();
			throw new ConectionException(e.getMessage());

		}
		catch (ConectionException e)
		{
			Util.gravaLog(e.getMessage());
			t = session.beginTransaction();
			throw e;
		}
		finally
		{
			if (session.isOpen())
				session.close();

		}

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> list() throws ConectionException
	{

		Session session = null;

		try
		{
			session = HibernateUtil.getSession().openSession();
			@SuppressWarnings("rawtypes")
			List lista = session.createCriteria(oClass).list();
			return (List<T>) lista;
		}
		catch (HibernateException e)
		{
			Util.gravaLog(e.getMessage());
			throw new ConectionException(e.getMessage());

		}
		catch (ConectionException e)
		{
			Util.gravaLog(e.getMessage());
			throw e;
		}
		finally
		{
			if (session.isOpen())
				session.close();

		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public T getById(Serializable id) throws ConectionException
	{
		Session session = null;
		try
		{
			session = HibernateUtil.getSession().openSession();
			return (T) session.get(oClass, id);
		}
		catch (HibernateException e)
		{
			Util.gravaLog(e.getMessage());
			throw new ConectionException(e.getMessage());

		}
		catch (ConectionException e)
		{
			Util.gravaLog(e.getMessage());
			throw e;
		}
		finally
		{
			if (session.isOpen())
			{
				session.close();
			}
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> consultaHQL(String consulta) throws ConectionException
	{
		Session session = null;
		try
		{
			session = HibernateUtil.getSession().openSession();
			return (List<T>) session.createQuery(consulta).list();
		}
		catch (HibernateException e)
		{
			Util.gravaLog(e.getMessage());
			throw new ConectionException(e.getMessage());

		}
		catch (ConectionException e)
		{
			Util.gravaLog(e.getMessage());
			throw e;
		}
		finally
		{
			if (session.isOpen())
			{
				session.close();
			}
		}

	}

}
